<?php
namespace app\services\weixin\pay;

/**
 * 微信支付
 * Created by PhpStorm.
 * User: fanxu(746439274@qq.com)
 * Date: 2015/8/5
 * Time: 15:15
 */
class WeiXinPay
{
    /**
     * @var null
     */
    private static $singleInstance = null;

    /**
     * 微信唯一的openid
     * @var string
     */
    private $_openId = '';

    /**
     * 用户ID
     * @var int
     */
    private $_userId = '';

    /**
     * 订单ID
     * @var int
     */
    private $_orderId = 0;

    /**
     * 微信支付订单缓存时间 10分钟
     */
    const ORDER_CACHE_TIME = 600;

    /**
     * 异步回调通知地址
     */
    const CALL_BACK_URL = 'http://wx.shpqkj.com/shwk1/weixinback/';

    /**
     * 薇凯微信支付订单描述
     */
    const ORDER_DESCRIPTION = 'order detail';

    /**
     * 构造函数
     * @param int $userId
     * @param int $openid
     */
    private function __construct(){
        require_once __DIR__ . "/lib/WxPayApi.php";
    }

    /**
     * @Author fanxu(746439274@qq.com)
     * @return WeiXinPay|null
     */
    public static function getInstance(){
        if(self::$singleInstance===null||!(self::$singleInstance instanceof self) ){
            self::$singleInstance = new self();
        }
        return self::$singleInstance;
    }

    /**
     * 获取jsAPI支付的参数
     * @Author fanxu(746439274@qq.com)
     * @return \成功时返回
     * @throws \WxPayException
     */
    public function getJsApiParam( $money , $orderId , $orderDescription ,$productId ){
        //金额到分
        $tools = new \WxPayApi();
        $input = $this->_getWxPayInput( true , $money , $orderId , $productId , $orderDescription , $orderId );
		

        $order = \WxPayApi::unifiedOrder($input);
        $jsApiParameters = $tools->GetJsApiParameters($order);
        //获取共享收货地址js函数参数
        $editAddress = $tools->GetEditAddressParameters();
        return array(
            'address'=>$editAddress,
            'js' => $jsApiParameters
        );
    }

    /**
     * 获取扫码支付的参数 需要回调生成订单
     * 流程：
     * 1、组装包含支付信息的url，生成二维码
     * 2、用户扫描二维码，进行支付
     * 3、确定支付之后，微信服务器会回调预先配置的回调地址，在【微信开放平台-微信支付-支付配置】中进行配置
     * 4、在接到回调通知之后，用户进行统一下单支付，并返回支付信息以完成支付（见：native_notify.php）
     * 5、支付完成之后，微信服务器会通知支付成功
     * 6、在支付成功通知中需要查单确认是否真正支付成功（见：notify.php）
     * @Author fanxu(746439274@qq.com)
     * @return \成功时返回
     * @throws \WxPayException
     */
    public function getNativeUrl(){
        //模式一 必须先生成订单
        $notify = new \NativePay();
        $url = $notify->GetPrePayUrl($this->_orderId);
        return $url;
    }

    /**
     * 获取扫码支付的参数
     * 流程：
     * 1、调用统一下单，取得code_url，生成二维码
     * 2、用户扫描二维码，进行支付
     * 3、支付完成之后，微信服务器会通知支付成功
     * 4、在支付成功通知中需要查单确认是否真正支付成功（见：notify.php）
     * @Author fanxu(746439274@qq.com)
     * @return \成功时返回
     * @throws \WxPayException
     */
    public function getStandardNativeUrl( $money , $orderId , $orderDescription ,$productId ){
        $input = $this->_getWxPayInput( false , $money , $orderId , $productId , $orderDescription , $orderId );
        $notify = new \NativePay();
        $result = $notify->GetPayUrl($input);
        $url = $result["code_url"];
        return $url;
    }

    /**
     * 生成付款二维码
     * @Author fanxu(746439274@qq.com)
     * @param $data
     */
    public static function qRcode( $data ){
        error_reporting(E_ERROR);
        require_once __DIR__ . "/example/phpqrcode/phpqrcode.php";
        $url = urldecode($data);
        \QRcode::png($url);
    }

    /**
     * @Author fanxu(746439274@qq.com)
     * @return \WxPayUnifiedOrder
     */
    private function _getWxPayInput( $isJs = false , $money , $orderId , $productId , $orderDescription , $attach ){
        $input = new \WxPayUnifiedOrder();
        $input->SetBody( "充值号：" . $orderId . $orderDescription );
        $input->SetAttach( $attach );
        $input->SetOut_trade_no(\WxPayConfig::MCHID.date("YmdHis"));
        $input->SetTotal_fee( $money );
        $input->SetTime_start(date("YmdHis"));
       // $input->SetTime_expire(date("YmdHis", time() + 300));
        $input->SetGoods_tag("饭卡在线充值" );
        $input->SetNotify_url(self::CALL_BACK_URL);
        $input->SetProduct_id( $orderId );
	if( !$isJs )
        	$input->SetTrade_type("NATIVE");
	else {
		$input->SetOpenid($this->_openId);
	        $input->SetTrade_type("JSAPI");
	}
        return $input;
    }

    /**
     * @return string
     */
    public function getOpenId()
    {
        return $this->_openId;
    }

    /**
     * @param string $openId
     * @return $this
     */
    public function setOpenId($openId)
    {
        $this->_openId = $openId;
        return $this;
    }

}
